/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import React, { useState, useRef, JSX } from 'react';
import { View, Text, Image, TouchableOpacity, StyleSheet, Dimensions, Platform, GestureResponderEvent } from 'react-native';

import PlaylistHeader from './PlaylistHeader';
import { songs, Track } from '../model';
import CurPlaySong from './CurPlaySong';

import musicPlayer from '../../util';

import { PlayListPageConstants } from '../../util/constants.tsx';
import { Menu, MenuOptions, MenuOption, MenuTrigger, MenuProvider, GestureDetector, Gesture } from '@hadss/react_native_uni_input';

import Animated, { useAnimatedStyle, useSharedValue, withSpring, runOnJS } from 'react-native-reanimated';

const { height } = Dimensions.get('window');

const SongList = ({ changePageShow }): JSX.Element => {
  const [songsList, setSongsList] = useState(songs);
  const [currentSong, setCurrentSong] = useState<Track>(songs[0]);
  const [isPlaying, setIsPlaying] = useState(false);
  // 判断是否是长按打开上下文
  const [isLongPressed, setIsLongPressed] = useState(false);
  // 删除数据()
  const deleteItem = (index: number): void => {
    setSongsList(songsList => songsList.filter((_item, index1) => index1 !== index));
  };

  // 收藏数据
  const collectItem = (index: number): void => {
    setSongsList(songsList => songsList.map((item1, index1) => (index1 === index ? { ...item1, hasCollect: true } : item1)));
  };
  // 取消收藏数据
  const deleteCollectItem = (index: number): void => {
    setSongsList(songsList => songsList.map((item1, index1) => (index1 === index ? { ...item1, hasCollect: false } : item1)));
  };

  // 滚动和轻扫--start
  const { height: SCREEN_HEIGHT } = Dimensions.get('window');
  // 用于跟踪滚动位置
  const translateY = useSharedValue(0);
  const startY = useSharedValue(0);
  const totalHeight = songs.length * PlayListPageConstants.ITEM_HEIGHT - SCREEN_HEIGHT + 270;

  // 轻扫
  const flingSongsList = Gesture.Fling()
    .minVelocity(800)
    .onStart((e): void => {
      // rotation<0,表示从下往上滑动+数据，rotation>0,表示从上往下滑动-数据，
      const { rotation } = e;
      const addListData = translateY.value - 10 * PlayListPageConstants.ITEM_HEIGHT;
      const removeListData = translateY.value + 10 * PlayListPageConstants.ITEM_HEIGHT;
      // 从下往上移动
      if (rotation < 0) {
        if (addListData >= -totalHeight) {
          // 若是没有到底，每次加10条数据的高度
          translateY.value = withSpring(addListData, { damping: 50 });
        } else {
          // 若是已经到底，不允许在轻扫
          translateY.value = withSpring(-totalHeight, { damping: 50 });
        }
      } else {
        // 从上往下移动
        if (removeListData < 0) {
          // 每次减10条数据的高度
          translateY.value = withSpring(removeListData, { damping: 50 });
        } else {
          // 若是已经到头，不允许在轻扫
          translateY.value = withSpring(0, { damping: 50 });
        }
      }
    });

  // 轻扫android
  const flingSongsListUp = Gesture.Fling()
    .direction('up')
    .minVelocity(800)
    .onStart((e): void => {
      // rotation<0,表示从下往上滑动+数据，rotation>0,表示从上往下滑动-数据，
      const addListData = translateY.value - 10 * PlayListPageConstants.ITEM_HEIGHT;
      const removeListData = translateY.value + 10 * PlayListPageConstants.ITEM_HEIGHT;
      // 从下往上移动
      if (addListData >= -totalHeight) {
        // 若是没有到底，每次加10条数据的高度
        translateY.value = withSpring(addListData, { damping: 50 });
      } else {
        // 若是已经到底，不允许在轻扫
        translateY.value = withSpring(-totalHeight, { damping: 50 });
      }
    });

  const flingSongsListDown = Gesture.Fling()
    .direction('down')
    .minVelocity(800)
    .onStart((e): void => {
      const addListData = translateY.value - 10 * PlayListPageConstants.ITEM_HEIGHT;
      const removeListData = translateY.value + 10 * PlayListPageConstants.ITEM_HEIGHT;
      // 从上往下移动
      if (removeListData < 0) {
        // 每次减10条数据的高度
        translateY.value = withSpring(removeListData, { damping: 50 });
      } else {
        // 若是已经到头，不允许在轻扫
        translateY.value = withSpring(0, { damping: 50 });
      }
    });

  const upOrDown = Gesture.Simultaneous(flingSongsList, flingSongsListDown);

  // 定义拖动手势s
  const panSongsList = Gesture.Pan()
    .minDistance(150)
    .onStart((e): void => {
      startY.value = translateY.value;
    })
    .onUpdate((e): void => {
      // 更新滚动位置
      translateY.value = startY.value + e.translationY;
      // 限制滚动范围
      const maxTranslateY = 0;
      if (translateY.value >= maxTranslateY) {
        // 从上往下拖动的最大值的限制
        translateY.value = withSpring(maxTranslateY, { damping: 50 });
      } else if (-(startY.value + e.translationY) > totalHeight) {
        // 从下往上拖动的最大值的限制
        translateY.value = withSpring(-totalHeight, { damping: 50 });
      }
    });

  // 创建动画样式
  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ translateY: translateY.value }],
  }));
  // 滚动和轻扫--end

  // 在点击列表后面的：的时候，获取点击位置给上下文组件
  const [position, setPosition] = useState({ top: 0, left: 0 });
  const calculateMenuPosition = (event: GestureResponderEvent): void => {
    setPosition({
      top: event.nativeEvent.pageY + 10,
      left: event.nativeEvent.pageX - 50,
    });
  };

  const showDetailPage = (item, isPlay): void => {
    changePageShow(false);
    musicPlayer.playTrackByIndex(item.songID, isPlay);
  };

  const renderItemMenu = (item: Track, index: number): JSX.Element => {
    return (
      <Menu
        onClose={(): void => {
          setTimeout(() => setIsLongPressed(false), 500);
        }}>
        <MenuTrigger
          triggerOnLongPress={true}
          onPress={(): void => {
            setIsLongPressed(true);
          }}>
          <Image source={require('../../../../asset/image/song_item_icon.png')} style={styles.songIcon} />
        </MenuTrigger>
        <MenuOptions
          optionsContainerStyle={[
            styles.optionList,
            {
              position: 'absolute',
              top: position.top,
              left: position.left,
            },
          ]}>
          <MenuOption onSelect={(): void => deleteItem(index)} style={{ flexDirection: 'row' }}>
            <Image source={require('../../../../asset/image/delete.png')} style={styles.songDelete} resizeMode="contain" />
            <Text style={styles.optionBtn}>{'删除'}</Text>
          </MenuOption>
          {item.hasCollect ? (
            <MenuOption onSelect={(): void => deleteCollectItem(index)} style={{ flexDirection: 'row' }}>
              <Image source={require('../../../../asset/image/deleteCollect.png')} style={styles.songDelete} resizeMode="contain" />
              <Text style={styles.optionBtn}>{'移除收藏'}</Text>
            </MenuOption>
          ) : (
            <MenuOption onSelect={(): void => collectItem(index)} style={{ flexDirection: 'row' }}>
              <Image source={require('../../../../asset/image/collect.png')} style={styles.songDelete} resizeMode="contain" />
              <Text style={styles.optionBtn}>{'收藏到歌单'}</Text>
            </MenuOption>
          )}
        </MenuOptions>
      </Menu>
    );
  };

  const renderItem = (item: Track, index: number): JSX.Element => (
    <MenuProvider skipInstanceCheck={true}>
      <View style={styles.songItem}>
        <View style={styles.songInfo}>
          <GestureDetector
            gesture={Gesture.Exclusive(
              Gesture.Tap()
                .minPointers(1)
                .numberOfTaps(2)
                .onStart((): void => {
                  runOnJS(showDetailPage)(item, true);
                }),
              Gesture.Tap()
                .minPointers(1)
                .onStart((event): void => {
                  // 防止在长按的时候触发单击
                  if (isLongPressed) {
                    return;
                  }
                  runOnJS(showDetailPage)(item, false);
                }),
            )}>
            <View style={styles.songInfoInner}>
              <Text style={styles.songTitle}>{item.title}</Text>
              {item.hasCollect ? <Image source={require('../../../../asset/image/music_love.png')} style={styles.liveIcon} /> : ''}
            </View>
            <View style={styles.vipStyle}>
              {item.isVip ? <Text style={styles.songVIPAndAudioType}>VIP</Text> : ''}
              {item.audioType ? <Text style={styles.songVIPAndAudioType}>{item.audioType}</Text> : ''}
              <Text style={styles.songArtist}>{item.artist}</Text>
            </View>
          </GestureDetector>
        </View>
        <View style={styles.menuOut} onTouchStart={calculateMenuPosition}>
          {renderItemMenu(item, index)}
        </View>
      </View>
    </MenuProvider>
  );
  return (
    <>
      <View style={{ backgroundColor: 'rgb(239, 239, 239)', flex: 1 }}>
        {/* 小屏下音乐列表的头部   */}
        <View
          style={{
            width: '100%',
            height: 150,
          }}>
          {<PlaylistHeader />}
        </View>
        <View style={{ flex: 1, overflow: 'hidden' }}>
          <GestureDetector
            gesture={
              Platform.OS === 'android' ? Gesture.Race(flingSongsListUp, flingSongsListDown, panSongsList) : Gesture.Exclusive(flingSongsList, panSongsList)
            }>
            <Animated.View style={[animatedStyle]}>
              {songsList.map(
                (item, index): JSX.Element => (
                  <View key={index} style={styles.item}>
                    {renderItem(item, index)}
                  </View>
                ),
              )}
            </Animated.View>
          </GestureDetector>
        </View>
      </View>
      <CurPlaySong song={currentSong} setCurrentSong={setCurrentSong} isPlaying={isPlaying} setIsPlaying={setIsPlaying} changePageShow={changePageShow} />
    </>
  );
};

const styles = StyleSheet.create({
  songItem: {
    flexDirection: 'row',
    height: 64,
    alignItems: 'center',
  },
  songInfo: {
    flexDirection: 'column',
    justifyContent: 'center',
    flex: 1,
  },
  menuOut: {
    marginRight: 15,
  },
  songTitle: {
    fontSize: 16,
    fontWeight: '500',
    lineHeight: 21,
    color: PlayListPageConstants.optionColor,
  },
  songArtist: {
    fontSize: 12,
    color: PlayListPageConstants.songIconColor,
    lineHeight: 16,
  },
  songVIPAndAudioType: {
    color: PlayListPageConstants.songVIPColor,
    fontSize: 10,
    lineHeight: 16,
    height: 16,
    backgroundColor: PlayListPageConstants.songInfoColor,
    borderRadius: 4,
    marginRight: 8,
    verticalAlign: 'middle',
    paddingHorizontal: 4,
  },
  songIcon: {
    width: 20,
    height: 20,
  },
  acoustic: {
    width: 16,
    height: 16,
  },
  list: {
    paddingBottom: height + PlayListPageConstants.ITEM_HEIGHT * 13, // 确保可以滚动到底部
  },
  item: {
    height: PlayListPageConstants.ITEM_HEIGHT,
    justifyContent: 'center',
    paddingLeft: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#eee',
  },
  optionList: {
    width: 150,
    borderRadius: 20,
    paddingVertical: 4,
    paddingHorizontal: 16,
    color: PlayListPageConstants.optionColor,
  },
  songDelete: {
    width: 15,
    height: 15,
    marginRight: 6,
  },
  optionBtn: {
    width: 150,
    fontSize: 16,
    fontWeight: '500',
  },
  songInfoInner: {
    flexDirection: 'row',
    top: 2,
    alignItems: 'center',
  },
  liveIcon: {
    width: 16,
    height: 14,
    marginLeft: 10,
  },
  vipStyle: {
    flexDirection: 'row',
    top: 2,
  },
});

export default React.memo(SongList);
